package com.x.bff.app.controller;

import com.x.bff.app.enums.AppErrorCode;
import com.x.bff.app.factory.customer.CustomerFactory;
import com.x.bff.app.model.vo.customer.*;
import com.x.bff.app.service.customer.CustomerService;
import com.x.core.utils.ApiAssetUtil;
import com.x.core.utils.BeanUtil;
import com.x.core.utils.SecurityUtils;
import com.x.core.web.api.R;
import com.x.core.web.controller.BaseFrontendController;
import com.x.core.web.page.PageList;
import com.x.provider.api.common.enums.ItemTypeEnum;
import com.x.provider.api.customer.enums.CustomerResourceOperBizScene;
import com.x.provider.api.customer.model.dto.customer.*;
import com.x.provider.api.customer.service.CustomerRpcService;
import com.x.provider.api.general.enums.ItemToggleRelationEnum;
import com.x.provider.api.general.enums.ItemToggleRelationTypeEnum;
import com.x.provider.api.general.model.dto.cms.ItemToggleRelationDTO;
import com.x.provider.api.general.model.dto.cms.ItemToggleRelationListReqDTO;
import com.x.provider.api.general.service.CmsRpcService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Objects;

@Api(tags = "用户服务")
@Slf4j
@Validated
@RestController
@RequestMapping("/app/customer")
public class CustomerController extends BaseFrontendController {

    private final CustomerService customerService;
    private final CustomerFactory customerFactory;
    private final CustomerRpcService customerRpcService;
    private final CmsRpcService cmsRpcService;

    public CustomerController(CustomerService customerService,
                              CustomerFactory customerFactory,
                              CustomerRpcService customerRpcService,
                              CmsRpcService cmsRpcService){
        this.customerService = customerService;
        this.customerFactory = customerFactory;
        this.customerRpcService = customerRpcService;
        this.cmsRpcService = cmsRpcService;
    }

    @ApiOperation(value = "第三方登陆，目前支持微信小程序, 返回token,下次方法其它接口是在此Token至于http header Authorization 中，值为 Bear token")
    @PostMapping("/login/external")
    public R<String> login(@RequestBody @Validated LoginExternalReqVO loginExternalReq){
        return R.ok(customerService.loginExternal(loginExternalReq));
    }

    @ApiOperation(value = "注销")
    @PostMapping("/logout")
    public R<Void> logout(){
        customerService.logout(SecurityUtils.getBearAuthorizationToken());
        return R.ok();
    }

    @ApiOperation(value = "修改用户名")
    @PostMapping("/user/name/update")
    public R<Void> changeCustomerUserName(@RequestBody @Validated CustomerUserNameUpdateReqVO customerUserNameUpdateReq){
        customerService.customerUserNameUpdate(getCurrentCustomerId(), customerUserNameUpdateReq);
        return R.ok();
    }

    @ApiOperation(value = "保存用户的资料信息")
    @PostMapping("/resume/save")
    public R<SaveResumeVO> saveResume(@RequestBody @Validated CustomerResumeSaveReqVO customerResumeSaveReq){
        return R.ok(customerService.saveResume(getCurrentCustomerId(), customerResumeSaveReq));
    }

    @ApiOperation(value = "保存用户的资料属性信息,用于保存昵称 头像 签名（择偶标准）")
    @PostMapping("/resume/attribute/save")
    public R<Void> saveResumeAttribute(@RequestBody @Validated CustomerResumeAttributeSaveReqVO reqVO){
        reqVO.setCustomerId(getCurrentCustomerId());
        customerService.saveResumeAttribute(reqVO);
        return R.ok();
    }

    @ApiOperation(value = "保存用户资料偏好")
    @PostMapping("/resume/preference/save")
    public R<Void> saveResumePreference(@RequestBody @Validated CustomerResumePreferenceSaveVO req){
        req.setCustomerId(getCurrentCustomerId());
        CustomerResumePreferenceSaveReqDTO reqDTO = BeanUtil.prepare(req, CustomerResumePreferenceSaveReqDTO.class);
        customerRpcService.saveCustomerResumePreference(reqDTO);
        return R.ok();
    }

    @ApiOperation(value = "个人主页信息")
    @GetMapping("/info")
    public R<CustomerVO> getCustomer(@RequestParam(required = false) @ApiParam(value = "用户id") Long customerId){
        if (customerId == null || customerId <= 0){
            customerId = getCurrentCustomerIdAndNotCheckLogin();
        }
        CustomerVO result = customerFactory.prepare(customerId, getCurrentCustomerIdAndNotCheckLogin());
        return R.ok(result);
    }

    @ApiOperation(value = "关注,取消关注")
    @PostMapping("/relation/follow/or/unfollow")
    public R<CustomerRelationVO> following(@NotNull @Min(1) @ApiParam(value = "用户id") @RequestParam Long toCustomerId,
                                           @NotNull @ApiParam(value = "true 关注 反之 false") @RequestParam Boolean follow){
        CustomerRelationDTO customerRelationNew = customerRpcService.updateCustomerRelation(CustomerRelationUpdateDTO.builder().follow(follow).fromCustomerId(getCurrentCustomerId())
                .toCustomerId(toCustomerId).build()).getData();
        return R.ok(BeanUtil.prepare(customerRelationNew, CustomerRelationVO.class));
    }

    @ApiOperation(value = "查询关注、粉丝、朋友信息")
    @GetMapping("/relation/list")
    public R<PageList<CustomerSimpleVO>> listCustomerRelation(@RequestParam(required = false) @ApiParam(value = "用户id") Long customerId,
                                                              @RequestParam @ApiParam(value = "关系 用户关系 1 关注 2 朋友 3 粉丝\"") Integer relation,
                                                              @RequestParam(required = false, defaultValue = "0") long cursor,
                                                              @RequestParam int pageSize){
        ApiAssetUtil.isTrue(Objects.equals(customerId, getCurrentCustomerId()), AppErrorCode.CUSTOMER_RELATION_ACCESS_FORBID);
        PageList<CustomerRelationDTO> relationList = customerRpcService.listMyCustomerRelation(CustomerRelationMyReqDTO.builder().customerId(customerId)
                .pageDomain(getPageDomain()).customerRelation(relation).build()).getData();
        if (relationList.isEmptyList()){
            return R.ok(new PageList<>());
        }

        return R.ok(relationList.map(customerFactory.prepareCustomerRelation(relationList.getList(), relation, getNullableCurrentCustomerId())));
    }

    @ApiOperation(value = "新增用户资源数量，返回用户资源总次数  包括：资料阅读次数 私信发送次数")
    @PostMapping("/resource/add")
    public R<Long> operateResource(@RequestParam @ApiParam(value = "业务场景 3 为了读取用户资料看广告 5 为了增加私信次数看广告") Integer bizScene){
        CustomerResourceOperBizScene.CustomerResourceAddBizSceneEnum bizSceneEnum = CustomerResourceOperBizScene.CustomerResourceAddBizSceneEnum.valueOf(bizScene);
        CustomerResourceOperReqDTO reqDTO = CustomerResourceOperReqDTO.builder().customerId(getCurrentCustomerId()).resourceId(bizSceneEnum.getResourceId())
                .operBizSceneId(bizSceneEnum.getId()).count(bizSceneEnum.getCount()).build();
        Long result = customerRpcService.operateCustomerResource(reqDTO).getData();
        return R.ok(result);
    }

    @ApiOperation(value = "减用户资源数量，返回剩余数量")
    @PostMapping("/resource/desc")
    public R<Long> operateResourceDesc(@RequestParam @ApiParam(value = "业务场景 1 资料阅读次数") Integer bizScene){
        return R.ok(customerRpcService.operateCustomerResource(CustomerResourceOperReqDTO.builder().count(-1L).customerId(getCurrentCustomerId())
                .resourceId(bizScene).build()).getData());
    }

    @ApiOperation(value = "身份证实名认证")
    @PostMapping("/verification/id/card")
    public R<Void> idCardVerification(@RequestParam @ApiParam(value = "身份证号") String idCard,
                                      @RequestParam @ApiParam(value = "姓名") String name){
        customerService.customerIdCardVerification(getCurrentCustomerId(), idCard, name);
        return R.ok();
    }

    @ApiOperation(value = "查询喜欢关系")
    @GetMapping("/star/list")
    public R<PageList<CustomerSimpleVO>> listCustomerStarRelation(@RequestParam(required = false) @ApiParam(value = "用户id") Long customerId,
                                                                  @ApiParam(value = "true 我喜欢的人， false 喜欢我的人 ") @RequestParam  Boolean myStar,
                                                                  @ApiParam(value = "相互喜欢的人")  @RequestParam Boolean bothStar,
                                                                  @RequestParam(required = false, defaultValue = "0") long cursor,
                                                                  @RequestParam int pageSize){
        ApiAssetUtil.isTrue(Objects.equals(customerId, getCurrentCustomerId()), AppErrorCode.CUSTOMER_RELATION_ACCESS_FORBID);
        ItemToggleRelationListReqDTO req = ItemToggleRelationListReqDTO.builder().relationType(ItemToggleRelationTypeEnum.STAR.getValue())
                .fromItemType(ItemTypeEnum.CUSTOMER.getValue()).toItemType(ItemTypeEnum.CUSTOMER.getValue()).bothRelation(bothStar).pageDomain(getPageDomain()).build();
        req.setRelation(bothStar != null ? null : ItemToggleRelationEnum.valueOf(true).getValue());
        PageList<ItemToggleRelationDTO> relationList = cmsRpcService.listItemToggleRelation(req).getData();
        if (relationList.isEmptyList()){
            return R.ok(new PageList<>(getPageDomain()));
        }
        return R.ok(relationList.map(customerFactory.prepareCustomerStarRelation(relationList.getList())));
    }

    @ApiOperation(value = "每天第一次登陆app时至少需要调用此接口，通过调用此接口可进行每日免费翻牌次数、每日私信发送次数等")
    @GetMapping("/ping")
    public R<PingVO> ping(){
        PingVO result = new PingVO();
        Long resumeReadCount = customerRpcService.operateCustomerResource(CustomerResourceOperReqDTO.builder()
                .operBizSceneId(CustomerResourceOperBizScene.CustomerResourceAddBizSceneEnum.ADD_RESUME_READ_COUNT_4_DAILY.getId()).customerId(getCurrentCustomerId()).build()).getData();
        Long imSendCount = customerRpcService.operateCustomerResource(CustomerResourceOperReqDTO.builder()
                .operBizSceneId(CustomerResourceOperBizScene.CustomerResourceAddBizSceneEnum.ADD_IM_SEND_COUNT_4_DAILY.getId()).customerId(getCurrentCustomerId()).build()).getData();
        result.setCustomerResourceSummaryVO(CustomerResourceSummaryVO.builder().customerId(getCurrentCustomerId()).imSendCount(imSendCount).resumeReadCount(resumeReadCount).build());
        return R.ok(result);
    }
}
